#include "fs.h"

#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define DUMMY_PREFIX "/stud/2000/nd/mha/myfs"

static char fname[1024];

char* realfilename(const char* old) {
  /* We don't check for .. in old */
  sprintf(fname, "%s/%s", DUMMY_PREFIX, old);
  return fname;
}

sd_info_t* sd_info(const char* filename) {
  static sd_info_t nfo;
  struct stat st;
  if (stat(realfilename(filename), &st)) return NULL;
  nfo.size = st.st_size;
  nfo.type = SD_FILETYPE;
  if (st.st_mode & S_IFDIR) nfo.type = SD_DIRTYPE;
  return &nfo;
}

char** sd_readdir(const char* dirname) {
  static char** files = NULL;
  char** tmpFiles;
  int nfile = 16;
  int filepos = 0;
  DIR* dirp;
  struct dirent* dp;
  if (files != NULL) {
    tmpFiles = files;
    while (*tmpFiles) free(tmpFiles++);
    free(files);
  }
  files = malloc(nfile * sizeof(char*));
  if (!(dirp = opendir(realfilename(dirname)))) return NULL;
  while (dp = readdir(dirp)) {
    if (filepos == nfile) {
      nfile *= 2;
      files = realloc(files, nfile * sizeof(char*));
    }
    files[filepos++] = strdup(dp->d_name);
  }
  if (filepos == nfile) files = realloc(files, (nfile+1)*sizeof(char*));
  files[filepos] = NULL;
  return files;
}

int sd_mkdir(const char* dirname) {
  return mkdir(realfilename(dirname), 0755);
}

int sd_rmdir(const char* dirname) {
  return rmdir(realfilename(dirname));
}

int sd_rmfile(const char* filename) {
  return unlink(realfilename(filename));
}

int sd_mount(const char* device, const char* mount_point) { return 0; }
int sd_umount(const char* mount_point) { return 0; }

int sd_open(const char* filename, int create) {
  int createflag = O_CREAT|O_TRUNC;
  if (!create) createflag = 0;
  return open(realfilename(filename), O_RDWR|createflag, 0644);
}
int sd_close(int fd) {
  return close(fd);
}

int sd_read(int fd, void* buf, int nbyte) {
  return read(fd, buf, nbyte);
}

int sd_write(int fd, const void* buf, int nbyte) {
  return write(fd, buf, nbyte);
}

int sd_rename(const char* oldname, const char* newname) {
  int ret_val;
  char* old = strdup(realfilename(oldname));
  ret_val = rename(old, realfilename(newname));
  free(old);
  return ret_val;
}
